#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
企业级构建监控 - 增强版Webhook接收器
集成Jpom + Prometheus + 钉钉通知
"""

import os
import json
import time
import hmac
import hashlib
import subprocess
import logging
import requests
from datetime import datetime
from flask import Flask, request, jsonify
from threading import Thread
import sqlite3

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s',
    handlers=[
        logging.FileHandler('/opt/jpom/logs/webhook-enhanced.log'),
        logging.StreamHandler()
    ]
)
logger = logging.getLogger(__name__)

app = Flask(__name__)

# 配置
GITEE_SECRET = "tetris_webhook_secret_2024"
PROJECT_PATH = "/opt/jpom/projects/tetris-game"
BUILD_SCRIPT = "/opt/jpom/projects/tetris-game/jpom-build.sh"
DB_PATH = "/opt/jpom/data/build_history.db"

# 钉钉机器人配置
DINGTALK_WEBHOOK = "https://oapi.dingtalk.com/robot/send?access_token=YOUR_TOKEN"
DINGTALK_SECRET = "YOUR_SECRET"

class BuildMonitor:
    def __init__(self):
        self.init_database()
    
    def init_database(self):
        """初始化构建历史数据库"""
        conn = sqlite3.connect(DB_PATH)
        cursor = conn.cursor()
        cursor.execute('''
            CREATE TABLE IF NOT EXISTS build_history (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                commit_hash TEXT,
                commit_message TEXT,
                author TEXT,
                branch TEXT,
                start_time TIMESTAMP,
                end_time TIMESTAMP,
                status TEXT,
                build_log TEXT,
                duration INTEGER
            )
        ''')
        conn.commit()
        conn.close()
    
    def record_build_start(self, commit_info):
        """记录构建开始"""
        conn = sqlite3.connect(DB_PATH)
        cursor = conn.cursor()
        cursor.execute('''
            INSERT INTO build_history 
            (commit_hash, commit_message, author, branch, start_time, status)
            VALUES (?, ?, ?, ?, ?, ?)
        ''', (
            commit_info.get('id', ''),
            commit_info.get('message', ''),
            commit_info.get('author', {}).get('name', ''),
            'main',
            datetime.now(),
            'BUILDING'
        ))
        build_id = cursor.lastrowid
        conn.commit()
        conn.close()
        return build_id
    
    def record_build_end(self, build_id, status, log_content, duration):
        """记录构建结束"""
        conn = sqlite3.connect(DB_PATH)
        cursor = conn.cursor()
        cursor.execute('''
            UPDATE build_history 
            SET end_time = ?, status = ?, build_log = ?, duration = ?
            WHERE id = ?
        ''', (datetime.now(), status, log_content, duration, build_id))
        conn.commit()
        conn.close()
    
    def get_build_stats(self):
        """获取构建统计"""
        conn = sqlite3.connect(DB_PATH)
        cursor = conn.cursor()
        
        # 最近10次构建
        cursor.execute('''
            SELECT * FROM build_history 
            ORDER BY start_time DESC 
            LIMIT 10
        ''')
        recent_builds = cursor.fetchall()
        
        # 成功率统计
        cursor.execute('''
            SELECT status, COUNT(*) as count 
            FROM build_history 
            WHERE start_time > datetime('now', '-7 days')
            GROUP BY status
        ''')
        status_stats = cursor.fetchall()
        
        conn.close()
        return {
            'recent_builds': recent_builds,
            'status_stats': status_stats
        }
    
    def send_dingtalk_notification(self, title, content, is_success=True):
        """发送钉钉通知"""
        if not DINGTALK_WEBHOOK or "YOUR_TOKEN" in DINGTALK_WEBHOOK:
            logger.info("钉钉通知未配置，跳过发送")
            return
        
        color = "green" if is_success else "red"
        emoji = "✅" if is_success else "❌"
        
        message = {
            "msgtype": "markdown",
            "markdown": {
                "title": f"{emoji} {title}",
                "text": f"## {emoji} {title}\n\n{content}\n\n> 时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}"
            }
        }
        
        try:
            response = requests.post(DINGTALK_WEBHOOK, json=message, timeout=10)
            if response.status_code == 200:
                logger.info("钉钉通知发送成功")
            else:
                logger.error(f"钉钉通知发送失败: {response.text}")
        except Exception as e:
            logger.error(f"发送钉钉通知异常: {e}")

monitor = BuildMonitor()

def verify_signature(payload, signature):
    """验证Gitee webhook签名"""
    expected_signature = hmac.new(
        GITEE_SECRET.encode('utf-8'),
        payload,
        hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(signature, expected_signature)

def execute_build(commit_info, build_id):
    """执行构建任务"""
    start_time = time.time()
    log_content = ""
    
    try:
        logger.info(f"开始构建 - Build ID: {build_id}")
        
        # 发送构建开始通知
        monitor.send_dingtalk_notification(
            "构建开始",
            f"**项目**: Tetris Game\n**提交**: {commit_info.get('message', 'N/A')}\n**作者**: {commit_info.get('author', {}).get('name', 'N/A')}"
        )
        
        # 执行构建脚本
        process = subprocess.Popen(
            ['bash', BUILD_SCRIPT],
            cwd=PROJECT_PATH,
            stdout=subprocess.PIPE,
            stderr=subprocess.STDOUT,
            universal_newlines=True
        )
        
        # 实时读取构建日志
        for line in iter(process.stdout.readline, ''):
            log_content += line
            logger.info(f"BUILD: {line.strip()}")
        
        process.wait()
        duration = int(time.time() - start_time)
        
        if process.returncode == 0:
            status = "SUCCESS"
            logger.info(f"构建成功 - Build ID: {build_id}, 耗时: {duration}秒")
            monitor.send_dingtalk_notification(
                "构建成功",
                f"**项目**: Tetris Game\n**耗时**: {duration}秒\n**状态**: 部署完成\n**访问**: http://onepiececrush.cn",
                True
            )
        else:
            status = "FAILED"
            logger.error(f"构建失败 - Build ID: {build_id}, 返回码: {process.returncode}")
            monitor.send_dingtalk_notification(
                "构建失败",
                f"**项目**: Tetris Game\n**错误码**: {process.returncode}\n**耗时**: {duration}秒\n**日志**: 请查看构建日志",
                False
            )
        
        # 记录构建结束
        monitor.record_build_end(build_id, status, log_content, duration)
        
    except Exception as e:
        duration = int(time.time() - start_time)
        logger.error(f"构建异常 - Build ID: {build_id}: {e}")
        monitor.record_build_end(build_id, "ERROR", str(e), duration)
        monitor.send_dingtalk_notification(
            "构建异常",
            f"**项目**: Tetris Game\n**异常**: {str(e)}\n**耗时**: {duration}秒",
            False
        )

@app.route('/webhook/gitee', methods=['POST'])
def handle_gitee_webhook():
    """处理Gitee webhook"""
    try:
        # 验证签名
        signature = request.headers.get('X-Gitee-Token', '')
        if not verify_signature(request.data, signature):
            logger.warning("Webhook签名验证失败")
            return jsonify({'error': 'Invalid signature'}), 403
        
        data = request.json
        
        # 只处理push事件
        if data.get('hook_name') != 'push_hooks':
            return jsonify({'message': 'Not a push event'}), 200
        
        # 提取提交信息
        commits = data.get('commits', [])
        if not commits:
            return jsonify({'message': 'No commits found'}), 200
        
        latest_commit = commits[-1]
        
        # 记录构建开始
        build_id = monitor.record_build_start(latest_commit)
        
        # 异步执行构建
        build_thread = Thread(
            target=execute_build,
            args=(latest_commit, build_id)
        )
        build_thread.daemon = True
        build_thread.start()
        
        return jsonify({
            'message': 'Build started',
            'build_id': build_id,
            'commit': latest_commit.get('id', '')[:8]
        }), 200
        
    except Exception as e:
        logger.error(f"处理webhook异常: {e}")
        return jsonify({'error': str(e)}), 500

@app.route('/api/builds', methods=['GET'])
def get_builds():
    """获取构建历史API"""
    try:
        stats = monitor.get_build_stats()
        return jsonify(stats), 200
    except Exception as e:
        logger.error(f"获取构建历史异常: {e}")
        return jsonify({'error': str(e)}), 500

@app.route('/health', methods=['GET'])
def health_check():
    """健康检查"""
    return jsonify({
        'status': 'healthy',
        'timestamp': datetime.now().isoformat(),
        'services': {
            'jpom': 'http://localhost:2122',
            'prometheus': 'http://localhost:9090',
            'grafana': 'http://localhost:3001'
        }
    }), 200

@app.route('/metrics', methods=['GET'])
def metrics():
    """Prometheus指标端点"""
    try:
        stats = monitor.get_build_stats()
        
        # 生成Prometheus格式指标
        metrics_text = "# HELP build_total Total number of builds\n"
        metrics_text += "# TYPE build_total counter\n"
        
        for status, count in stats['status_stats']:
            metrics_text += f'build_total{{status="{status.lower()}"}} {count}\n'
        
        return metrics_text, 200, {'Content-Type': 'text/plain'}
    except Exception as e:
        logger.error(f"生成指标异常: {e}")
        return "# Error generating metrics\n", 500, {'Content-Type': 'text/plain'}

if __name__ == '__main__':
    logger.info("启动增强版Webhook接收器...")
    app.run(host='0.0.0.0', port=9999, debug=False)
